<template>
  <div class="system-management">
    <div class="page-header">
      <div class="title">系统管理概览</div>
      <div class="actions">
        <el-button type="primary" :loading="loadingAll" @click="loadAll">
          <el-icon><Refresh /></el-icon>
          刷新
        </el-button>
      </div>
    </div>

    <!-- 顶部指标卡 -->
    <el-row :gutter="16" class="metrics-row">
      <el-col :xs="24" :sm="12" :md="6">
        <el-card shadow="hover" class="metric-card">
          <div class="metric-title">健康状态</div>
          <div class="metric-value">
            <el-tag :type="healthTagType">{{ healthText }}</el-tag>
          </div>
          <div class="metric-sub">{{ healthSubText }}</div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="12" :md="6">
        <el-card shadow="hover" class="metric-card">
          <div class="metric-title">服务运行时间</div>
          <div class="metric-value">{{ uptime }}</div>
          <div class="metric-sub">来自系统信息</div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="12" :md="6">
        <el-card shadow="hover" class="metric-card">
          <div class="metric-title">向量任务</div>
          <div class="metric-value">{{ vectorTaskSummary }}</div>
          <div class="metric-sub">向量化处理状态</div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="12" :md="6">
        <el-card shadow="hover" class="metric-card">
          <div class="metric-title">数据总览</div>
          <div class="metric-value">{{ dashboardSummary }}</div>
          <div class="metric-sub">仪表盘统计</div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 主体信息块 -->
    <el-row :gutter="16" class="content-row">
      <el-col :xs="24" :md="12">
        <el-card shadow="hover" class="info-card" v-loading="loadingInfo">
          <template #header>
            <div class="card-header">
              <span>系统信息</span>
              <el-tag size="small" type="info">基础</el-tag>
            </div>
          </template>
          <el-descriptions :column="1" border>
            <el-descriptions-item label="应用名称">{{ pick(systemInfo, ['appName','name','applicationName'], '-') }}</el-descriptions-item>
            <el-descriptions-item label="版本">{{ pick(systemInfo, ['version','appVersion'], '-') }}</el-descriptions-item>
            <el-descriptions-item label="环境">{{ pick(systemInfo, ['env','environment','profile'], '-') }}</el-descriptions-item>
            <el-descriptions-item label="启动时间">{{ pick(systemInfo, ['startTime','startedAt','bootTime'], '-') }}</el-descriptions-item>
            <el-descriptions-item label="服务端口">{{ pick(systemInfo, ['port','serverPort'], '-') }}</el-descriptions-item>
          </el-descriptions>
        </el-card>
      </el-col>

      <el-col :xs="24" :md="12">
        <el-card shadow="hover" class="info-card" v-loading="loadingSupportedTypes">
          <template #header>
            <div class="card-header">
              <span>支持的文件类型</span>
              <el-tag size="small" type="success">上传</el-tag>
            </div>
          </template>
          <div class="file-types">
            <template v-if="Array.isArray(supportedFileTypes) && supportedFileTypes.length">
              <el-tag v-for="t in supportedFileTypes" :key="t" class="type-tag" round>{{ t }}</el-tag>
            </template>
            <el-empty v-else description="暂无数据" />
          </div>
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="16" class="content-row">
      <el-col :xs="24" :md="12">
        <el-card shadow="hover" class="info-card" v-loading="loadingVectorStatus">
          <template #header>
            <div class="card-header">
              <span>向量化处理状态</span>
              <el-tag size="small" type="warning">向量</el-tag>
            </div>
          </template>
          <div class="progress-list" v-if="vectorizationStatusItems.length">
            <div v-for="item in vectorizationStatusItems" :key="item.label" class="progress-item">
              <div class="progress-label">{{ item.label }}</div>
              <el-progress :percentage="item.percent" :status="item.status" :stroke-width="12" />
            </div>
          </div>
          <el-empty v-else description="暂无任务" />
        </el-card>
      </el-col>

      <el-col :xs="24" :md="12">
        <el-card shadow="hover" class="info-card" v-loading="loadingStatistics">
          <template #header>
            <div class="card-header">
              <span>系统统计</span>
              <el-tag size="small" type="info">统计</el-tag>
            </div>
          </template>
          <el-table :data="statisticsTable" size="small" border>
            <el-table-column prop="name" label="指标" width="160" />
            <el-table-column prop="value" label="值" />
          </el-table>
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="16" class="content-row">
      <el-col :xs="24" :md="12">
        <el-card shadow="hover" class="info-card" v-loading="loadingAnalytics">
          <template #header>
            <div class="card-header">
              <span>系统分析报告</span>
              <el-tag size="small" type="primary">分析</el-tag>
            </div>
          </template>
          <div class="json-view" v-if="analyticsJson">
            <pre>{{ analyticsJson }}</pre>
          </div>
          <el-empty v-else description="暂无数据" />
        </el-card>
      </el-col>

      <el-col :xs="24" :md="12">
        <el-card shadow="hover" class="info-card" v-loading="loadingAnalyticsEx">
          <template #header>
            <div class="card-header">
              <span>系统分析（扩展版）</span>
              <el-tag size="small" type="primary">扩展</el-tag>
            </div>
          </template>
          <div class="json-view" v-if="analyticsExJson">
            <pre>{{ analyticsExJson }}</pre>
          </div>
          <el-empty v-else description="暂无数据" />
        </el-card>
      </el-col>
    </el-row>
  </div>
 </template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import {
  getSystemStatistics,
  getSystemInfo,
  getSystemHealth,
  getSupportedFileTypes,
  getSystemAnalytics,
  getVectorizationStatus,
  getSystemHealthStatus,
  getSystemDetailedInfo,
  getVectorizationDetailedStatus,
  getSystemAnalyticsExtended,
  getDashboardStatistics
} from '@/api/system'
import { getUserList } from '@/api/user'
import { getDocumentList } from '@/api/document'
import { getKnowledgeBaseList } from '@/api/knowledgeBase'
import { getVectorList } from '@/api/vector'

const loadingAll = ref(false)
const loadingInfo = ref(false)
const loadingStatistics = ref(false)
const loadingHealth = ref(false)
const loadingSupportedTypes = ref(false)
const loadingAnalytics = ref(false)
const loadingVectorStatus = ref(false)
const loadingAnalyticsEx = ref(false)

const systemInfo = ref({})
const systemStatistics = ref({})
const supportedFileTypes = ref([])
const systemHealth = ref({})
const systemHealthStatus = ref({})
const vectorizationStatus = ref({})
const vectorizationDetailed = ref({})
const analytics = ref(null)
const analyticsEx = ref(null)
const dashboardStats = ref({})

function pick(obj, keys, fallback = '-') {
  if (!obj) return fallback
  for (const k of keys) {
    const v = obj[k]
    if (v !== undefined && v !== null && v !== '') return v
  }
  return fallback
}

const healthOk = computed(() => {
  const h = systemHealth.value
  const statusVal = pick(h, ['status','health','ok'], '')
  if (typeof statusVal === 'boolean') return statusVal
  const s = String(statusVal).toLowerCase()
  return s === 'up' || s === 'ok' || s === 'healthy' || s === 'true'
})

const healthText = computed(() => (healthOk.value ? '健康' : '异常'))
const healthTagType = computed(() => (healthOk.value ? 'success' : 'danger'))
const healthSubText = computed(() => pick(systemHealthStatus.value, ['message','desc','detail'], ''))

const uptime = computed(() => pick(systemInfo.value, ['uptime','upTime','runTime','runtime'], '-'))

const vectorTaskSummary = computed(() => {
  const d = vectorizationStatus.value || {}
  const pending = Number(pick(d, ['pending','queue','waiting'], 0))
  const running = Number(pick(d, ['running','processing','inProgress'], 0))
  const done = Number(pick(d, ['done','completed','finished'], 0))
  return `${done}/${running}/${pending}`
})

const dashboardSummary = computed(() => {
  const d = dashboardStats.value || {}
  const users = Number(pick(d, ['users','userCount','totalUsers','userTotal'], 0))
  const docs = Number(pick(d, ['documents','docCount','totalDocuments','documentTotal'], 0))
  const vectors = Number(pick(d, ['vectors','vectorCount','totalVectors','vectorTotal'], 0))
  return `${users} 用户 · ${docs} 文档 · ${vectors} 向量`
})

const vectorizationStatusItems = computed(() => {
  const d = vectorizationDetailed.value || {}
  const items = []
  const map = {
    queued: '排队',
    processing: '处理中',
    completed: '完成',
    failed: '失败'
  }
  for (const key in map) {
    const val = Number(pick(d, [key], 0))
    const percent = Math.max(0, Math.min(100, val))
    items.push({ label: map[key], percent, status: key === 'failed' ? 'exception' : 'success' })
  }
  return items.filter(i => i.percent > 0)
})

const statisticsTable = computed(() => {
  const s = systemStatistics.value || {}
  const rows = []
  const pairs = [
    ['CPU 使用率', pick(s, ['cpuUsage','cpu','cpuPercent'], '-')],
    ['内存使用', pick(s, ['memoryUsage','memory','mem'], '-')],
    ['磁盘使用', pick(s, ['diskUsage','disk','storage'], '-')],
    ['请求数', pick(s, ['requestCount','requests'], '-')],
    ['错误数', pick(s, ['errorCount','errors'], '-')],
    ['平均响应(ms)', pick(s, ['avgResponseTime','avgRt'], '-')]
  ]
  for (const [name, value] of pairs) rows.push({ name, value })
  return rows
})

const analyticsJson = computed(() => (analytics.value ? formatJson(analytics.value) : ''))
const analyticsExJson = computed(() => (analyticsEx.value ? formatJson(analyticsEx.value) : ''))

function formatJson(v) {
  try {
    return JSON.stringify(v, null, 2)
  } catch (_) {
    return String(v)
  }
}

async function loadAll() {
  loadingAll.value = true
  try {
    const unwrap = (r) => (r && r.data !== undefined ? r.data : r)
    await Promise.all([
      (async () => { loadingInfo.value = true; systemInfo.value = unwrap(await getSystemInfo()) ?? {}; })(),
      (async () => { loadingStatistics.value = true; systemStatistics.value = unwrap(await getSystemStatistics()) ?? {}; })(),
      (async () => { loadingHealth.value = true; systemHealth.value = unwrap(await getSystemHealth()) ?? {}; })(),
      (async () => { loadingSupportedTypes.value = true; supportedFileTypes.value = unwrap(await getSupportedFileTypes()) ?? []; })(),
      (async () => { loadingAnalytics.value = true; analytics.value = unwrap(await getSystemAnalytics()) ?? null; })(),
      (async () => { loadingVectorStatus.value = true; vectorizationStatus.value = unwrap(await getVectorizationStatus()) ?? {}; })(),
      (async () => { systemHealthStatus.value = unwrap(await getSystemHealthStatus()) ?? {}; })(),
      (async () => { vectorizationDetailed.value = unwrap(await getVectorizationDetailedStatus()) ?? {}; })(),
      (async () => { analyticsEx.value = unwrap(await getSystemAnalyticsExtended()) ?? null; })(),
      (async () => { dashboardStats.value = unwrap(await getDashboardStatistics()) ?? {}; })()
    ])

    // 如果仪表盘接口没有返回有效总数，则用现有列表接口推导统计
    await backfillDashboardCounts()
  } catch (e) {
    console.error('加载系统信息失败', e)
    ElMessage.error('部分系统信息加载失败')
  } finally {
    loadingAll.value = false
    loadingInfo.value = false
    loadingStatistics.value = false
    loadingHealth.value = false
    loadingSupportedTypes.value = false
    loadingAnalytics.value = false
    loadingVectorStatus.value = false
    loadingAnalyticsEx.value = false
  }
}

onMounted(loadAll)

// 通过现有列表接口补齐统计数据
async function backfillDashboardCounts() {
  try {
    const d = dashboardStats.value || {}
    const hasUsers = toNumber(pick(d, ['users','userCount','totalUsers','userTotal'], undefined)) > 0
    const hasDocs = toNumber(pick(d, ['documents','docCount','totalDocuments','documentTotal'], undefined)) > 0
    const hasVectors = toNumber(pick(d, ['vectors','vectorCount','totalVectors','vectorTotal'], undefined)) > 0

    const tasks = []

    if (!hasUsers) {
      tasks.push((async () => {
        const res = await getUserList({ page: 1, size: 1 })
        const data = res && res.data !== undefined ? res.data : res
        const total = extractTotalCount(data)
        d.users = total
      })())
    }

    if (!hasVectors) {
      tasks.push((async () => {
        const res = await getVectorList({ page: 1, size: 1 })
        const data = res && res.data !== undefined ? res.data : res
        const total = extractTotalCount(data)
        d.vectors = total
      })())
    }

    if (!hasDocs) {
      tasks.push((async () => {
        // 尝试直接获取所有文档总数
        let total = 0
        try {
          const resAll = await getDocumentList(undefined, { page: 1, size: 1 })
          const dataAll = resAll && resAll.data !== undefined ? resAll.data : resAll
          total = extractTotalCount(dataAll)
        } catch (_) {
          total = 0
        }
        // 如果拿不到，再按知识库汇总
        if (!total) {
          try {
            const kbRes = await getKnowledgeBaseList({ page: 1, size: 1000 })
            const kbData = kbRes && kbRes.data !== undefined ? kbRes.data : kbRes
            const kbs = Array.isArray(kbData) ? kbData : (kbData?.records || kbData?.list || kbData?.content || [])
            const counts = await Promise.all(
              (kbs || []).map(async kb => {
                try {
                  const id = kb.knowledgeBaseId || kb.id
                  const r = await getDocumentList(id, { page: 1, size: 1 })
                  const d = r && r.data !== undefined ? r.data : r
                  return extractTotalCount(d)
                } catch { return 0 }
              })
            )
            total = counts.reduce((a, b) => a + (Number(b) || 0), 0)
          } catch (_) {
            total = 0
          }
        }
        d.documents = total
      })())
    }

    if (tasks.length) {
      await Promise.allSettled(tasks)
      dashboardStats.value = { ...d }
    }
  } catch (err) {
    console.warn('补齐仪表盘统计失败:', err)
  }
}

function extractTotalCount(payload) {
  if (!payload) return 0
  // 常见分页结构
  const total = payload.total ?? payload.totalElements ?? payload.totalCount ?? payload.count
  if (total !== undefined) return Number(total) || 0
  const list = payload.records || payload.list || payload.rows || payload.content || payload.items
  if (Array.isArray(list)) return list.length
  if (Array.isArray(payload)) return payload.length
  return 0
}

function toNumber(v) { const n = Number(v); return Number.isFinite(n) ? n : 0 }
</script>

<style scoped>
.system-management {
  padding: 24px;
  background: linear-gradient(135deg, #eef2ff 0%, #e9d5ff 100%);
  min-height: calc(100vh - 120px);
  box-sizing: border-box;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.title {
  font-size: 20px;
  font-weight: 600;
  color: #334155;
}

.metrics-row,
.content-row {
  max-width: 1400px;
  margin: 0 auto 16px auto;
}

.metric-card {
  text-align: center;
}
.metric-title {
  color: #64748b;
  font-size: 13px;
}
.metric-value {
  margin-top: 8px;
  font-size: 22px;
  font-weight: 700;
  color: #1f2937;
}
.metric-sub {
  margin-top: 6px;
  font-size: 12px;
  color: #94a3b8;
}

.card-header {
  display: flex;
  gap: 8px;
  align-items: center;
}

.file-types {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.type-tag {
  background: linear-gradient(135deg, #dbeafe 0%, #e9d5ff 100%);
  border: none;
}

.progress-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.progress-item {
  display: grid;
  grid-template-columns: 80px 1fr;
  align-items: center;
  gap: 12px;
}
.progress-label {
  color: #475569;
  font-size: 13px;
}

.json-view {
  max-height: 260px;
  overflow: auto;
  background: rgba(255, 255, 255, 0.7);
  border-radius: 6px;
  padding: 8px 12px;
}
.json-view pre {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
  font-size: 12px;
}
</style>

